package cn.huiyunche.driver.service.impl;

import cn.huiyunche.base.service.enums.DWaybillFeeDetailCostTypeEnum;
import cn.huiyunche.base.service.enums.DWaybillStatusEnum;
import cn.huiyunche.base.service.enums.DWaybillStatusTypeEnum;
import cn.huiyunche.base.service.framework.utils.JdbcTemplateUtils;
import cn.huiyunche.base.service.framework.utils.TmsQueueApi;
import cn.huiyunche.base.service.interfaces.*;
import cn.huiyunche.base.service.mappers.DWaybillMapper;
import cn.huiyunche.base.service.mappers.TmsOrderMapper;
import cn.huiyunche.base.service.model.*;
import cn.huiyunche.base.service.utils.DateUtils;
import cn.huiyunche.base.service.utils.ValidationParams;
import cn.huiyunche.base.service.vo.OrderConfirmResult;
import cn.huiyunche.base.service.vo.OrderCostTo;
import cn.huiyunche.base.service.vo.OrderDepartureVo;
import cn.huiyunche.base.service.vo.TmsQueueOrderVo;
import cn.huiyunche.driver.service.OrderService;
import cn.huiyunche.driver.service.WaybillGenerateResultsService;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintViolation;
import org.joda.time.DateTime;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @FileName: cn.huiyunche.service.base.tms.interfaces.impl
 * @Description: Description
 * @author: Aaron
 * @date: 2016/11/2 上午9:57
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(cn.huiyunche.base.service.interfaces.impl.TmsOrderServiceImpl.class);

    @Autowired
    private TmsOrderMapper tmsOrderMapper;

    @Autowired
    private TmsOrderValidationResultService tmsOrderValidationResultService;

    @Autowired
    private DWaybillService dWaybillService;

    @Autowired
    private DWaybillStatusHistoryService dWaybillStatusHistoryService;

    @Autowired
    private TmsQueueService tmsQueueService;

    @Autowired
    private DWaybillMapper dWaybillMapper;

    @Autowired
    private TmsOrderService tmsOrderService;

    @Autowired
    private UserService userService;

    @Autowired
    private CAccntTurnOverService cAccntTurnOverService;

    @Autowired
    private SendMessageService sendMessageService;

    @Autowired
    private WaybillGenerateResultsService waybillGenerateResultsService;

    /**
     * 验证TMS订单各字段并保存校验结果
     *
     * @param tmsOrders
     */
    @Override
    public void handleTmsOrders(List<TmsOrder> tmsOrders) {
        LOGGER.info("OrderServiceImpl.handleTmsOrders param : {}", tmsOrders);

        if (CollectionUtils.isEmpty(tmsOrders)) {
            LOGGER.error("OrderServiceImpl.handleTmsOrders tms orders must not be null");
            throw new BusinessException("运单不能为空");
        }

        tmsOrders.forEach(tmsOrder -> {

            /**
             * 流水号不存在的订单才导入(唯一性验证)
             */

            boolean exist = this.isAlreadyExist(tmsOrder.getIlineid());

            if (exist) {
                LOGGER.error("OrderServiceImpl.handleTmsOrders tms order already exist : {}", tmsOrder);
            } else {
                /**
                 * 保存tms订单
                 */
                Long tmsOrderId = tmsOrderService.add(tmsOrder);

                // 保存订单校验结果
                TmsOrderValidationResult vr = new TmsOrderValidationResult();
                vr.setOrderId(tmsOrderId);
                vr.setIsValidationPassed(true);

                // 验证字段
                Set<ConstraintViolation<Object>> set = ValidationParams.validation(tmsOrder);
                if (CollectionUtils.isNotEmpty(set)) {
                    String errorMsg = set.stream().map(vc -> vc.getMessage())
                            .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();
                    vr.setIsValidationPassed(false);
                    vr.setMessage(errorMsg);
                }

                /**
                 * 保存订单验证结果
                 */
                tmsOrderValidationResultService.add(vr);

                // 校验通过保存运单
                if (vr.getIsValidationPassed()) {
                    try {
                        //处理运单
                        DWaybill waybill = dWaybillService.addByTmsOrder(tmsOrder);

                        //添加队列
                        //20170328 liangpeng 去掉订单添加到redis操作，原因是会影响派单顺序，造成后排队司机先接单。
                        //this.addQueue(tmsOrder, waybill);
                    } catch (Exception e) {
                        LOGGER.error("OrderServiceImpl.handleTmsOrders error : {}", e);

                        //存储错误记录
//                        WaybillGenerateResults generateResults = new WaybillGenerateResults();
//                        generateResults.setOrderId(tmsOrderId);
//                        generateResults.setIsGenerated(false);
//                        generateResults.setErrMsg(e.getMessage());
//                        waybillGenerateResultsService.addWaybillGenerateResults(generateResults);
                    }
                }
            }
        });
    }

    /**
     * 检查运单是否取消状态
     *
     * @param ilineid
     */
    private void checkDwaybillIsCancel(Long ilineid) throws Exception {
        DWaybillExample dwe = new DWaybillExample();
        dwe.createCriteria().andOrderLineIdEqualTo(ilineid).andUserIdEqualTo(-1L)
                .andWaybillStatusEqualTo(DWaybillStatusEnum.FAILURE.getValue());
        List<DWaybill> list = this.dWaybillMapper.selectByExample(dwe);
        DWaybill dw = list.size() > 0 ? list.get(0) : null;
        if (null != dw) {
            LOGGER.info("checkDwaybillIsCancel，获取取消运单信息：{}", JSONObject.toJSONString(dw));
            // 将运单取消状态回滚到初始化状态
            DWaybill newDw = new DWaybill();
            newDw.setId(dw.getId());
            newDw.setUserId(0L);
            newDw.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
            this.dWaybillMapper.updateByPrimaryKeySelective(newDw);
            LOGGER.info("checkDwaybillIsCancel，修改运单状态：{}", JSONObject.toJSONString(newDw));
            // 加入队列
            TmsQueueOrderVo tqov = new TmsQueueOrderVo();
            tqov.setWaybillId(dw.getId().toString());
            tqov.setTmsSerialNo(dw.getOrderLineId().toString());
            tqov.setFrom(dw.getDepartureCity());
            tqov.setTo(dw.getDestCity());
            tqov.setUrgent(dw.getIsUrgent());
            this.tmsQueueService.appendOrder(tqov);
            LOGGER.info("checkDwaybillIsCancel，添加运单到队列：{}", JSONObject.toJSONString(tqov));
            // 添加日志
            this.dWaybillStatusHistoryService.add(dw.getId(), DWaybillStatusTypeEnum.PROCESS.getText(),
                    DWaybillStatusEnum.SAVE.getText(), DWaybillStatusEnum.getByValue(dw.getWaybillStatus()).getText(),
                    0L, "系统重置");
        }
    }

    @Override
    public void orderDeparture(List<OrderDepartureVo> odvList) throws Exception {
        for (OrderDepartureVo odv : odvList) {

//			 OrderCostTo orderCostTo = new OrderCostTo(); if (StringUtils.isNotBlank(odv.getOrdercost())) { orderCostTo = JSONObject.parseObject(odv.getOrdercost().replaceAll("\"", ""), OrderCostTo.class); }

            // 获取运单数据
            DWaybill dw = this.dWaybillService.getByTmsOrderCode(odv.getVcorderno());
            if (null == dw) {
                continue;
            }
            String dtshipdate = odv.getDtshipdate();
            if (StringUtils.isBlank(dtshipdate)) {
                LOGGER.info("发车时间为空，不做处理，订单号：{}", dw.getOrderCode());
                continue;
            }
            if (dw.getWaybillStatus() != DWaybillStatusEnum.DEPARTURE.getValue()) {
                LOGGER.info("orderDeparture 运单状态不是待发车，只更新发车时间，跳过此条记录状态变更");
                dw.setOutsetTime(DateUtils.StrToDate(dtshipdate, DateUtils.FORMAT_DATETIME));
                this.dWaybillMapper.updateByPrimaryKeySelective(dw);
                continue;
            }
            // 修改状态
            dw.setWaybillStatus(DWaybillStatusEnum.INTRANSIT.getValue());
            dw.setOutsetTime(DateUtils.StrToDate(dtshipdate, DateUtils.FORMAT_DATETIME));
            this.dWaybillMapper.updateByPrimaryKeySelective(dw);

//			//更新价格
//			if (null != orderCostTo) {
//
//				//更新确认价格
//				TmsOrder tmsOrder = tmsOrderService.getTmsOrderByIlineid(dw.getOrderLineId());
//				if(null != tmsOrder){
//					tmsOrderService.updateConfirmCost(tmsOrder.getId(), odv.getOrdercost(), new Date());
//				}
//
//				this.dWaybillService.calcDWaybillCost(dw.getId(), orderCostTo, true);
//			}

            // 添加日志
            dWaybillStatusHistoryService.add(dw.getId(), DWaybillStatusTypeEnum.PROCESS.getText(),
                    DWaybillStatusEnum.INTRANSIT.getText(),
                    DWaybillStatusEnum.getByValue(dw.getWaybillStatus()).getText(), 0L, "系统发车");
            LOGGER.info("orderDeparture 运单发车状态修改成功: {}", dw.getId());

            SUser user = userService.selectByPrimaryKey(dw.getUserId());
            BigDecimal assessTime = dw.getDistance().divide(new BigDecimal("550"),0,BigDecimal.ROUND_UP).add(new BigDecimal("1"));
            String beginDateTime = DateTime.now().plusDays(assessTime.intValue()).toString("yyyy年MM月dd日");
            // push消息给司机 TODO司机发短信注释
            sendMessageService.sendDepartureMessage(dw.getOrderCode(), beginDateTime ,user.getPhone());
        }
    }

    @Override
    public boolean isAlreadyExist(Long ilineid) {
        LOGGER.info("isAlreadyExist param : {}", ilineid);
        if (null == ilineid) {
            LOGGER.error("isAlreadyExist param must not be null");
            throw new IllegalArgumentException("订单流水号不能为空");
        }

        TmsOrderExample example = new TmsOrderExample();
        example.createCriteria().andIlineidEqualTo(ilineid);

        List<TmsOrder> list = tmsOrderMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(list)) {
            return true;
        }
        return false;
    }

    @Override
    public void confirmResult(Long waybillId) throws Exception {
        DWaybill waybill = dWaybillService.getByPrimaryId(waybillId);
        if (null != waybill) {
            OrderConfirmResult result = new OrderConfirmResult();
            result.setDtreturn(new Date());
            result.setIlineid(waybill.getOrderLineId());
            result.setVcorderno(waybill.getOrderCode());
            result.setOrdercost(null);

            List<OrderConfirmResult> resultList = new ArrayList<>();
            resultList.add(result);

            this.confirmResults(resultList);
        }
    }

    @Override
    public void confirmResults(List<OrderConfirmResult> confirmResults) {
        LOGGER.info("confirmResults params : {}", confirmResults.size());
        List<JSONObject> userPhoneList = new ArrayList<>();
        try {
            for (OrderConfirmResult or : confirmResults) {

                try {
                    // 存储回单价格
                    TmsOrder order = tmsOrderService.getTmsOrderByIlineid(or.getIlineid());
                    if (null != order) {
                        //修改回单时间，回单价格
                        tmsOrderService.updateConfirmCost(order.getId(), or.getOrdercost(), or.getDtreturn());

                        // 更新运单确认价格
                        DWaybill waybill = dWaybillService.getCompletedByTmsIlineid(or.getIlineid());
                        if (null != waybill) {
                            int waybillStatus = waybill.getWaybillStatus();
                            //BigDecimal confirmTotalCost = dWaybillService.computeOrderCost(or.getOrdercost(), true,
                            //		waybill.getId());

                            if(or.getDtreturn()!=null){
                                // 更新订单状态为已完成
                                LOGGER.info("confirmResults update waybill status: {}, status:{}, returnDate:{}", waybill.getOrderCode(), DWaybillStatusEnum.COMPLETED.getValue(), or.getDtreturn());

                                dWaybillService.updateWaybillStatusAndRecoveryTime(waybill.getId(), DWaybillStatusEnum.COMPLETED.getValue(), or.getDtreturn());

                                // 将用户强制下线 重新排队
                                SUser user = userService.getById(waybill.getUserId());
                                /*if (!(waybillStatus == DWaybillStatusEnum.EXCEPTION_CONFIRM.getValue() || waybillStatus == DWaybillStatusEnum.COMPLETED.getValue())) {
                                    if (user.getUserStatus() == UserStatusEnum.T.getValue()) {
                                        user.setUserStatus(UserStatusEnum.F.getValue());
                                        userService.updateByRecord(user);
                                    }
                                }*/

                                // 短信对象
                                JSONObject j = new JSONObject();
                                j.put("phone", user.getPhone());
                                j.put("orderCode", waybill.getOrderCode());
                                userPhoneList.add(j);
                                // 添加账单
                                LOGGER.info("confirmResults.add bill: {}, confirmcost:{}, phone:{} ", waybill.getId(), waybill.getConfirmTotalCost(), user.getPhone());
                                cAccntTurnOverService.addSendByDriverCost(waybill.getId(), waybill.getTotalShippingCost(), user.getId());
                            }

                        }
                    }
                } catch (Exception e) {
                    LOGGER.error("OrderServiceImpl.confirmResults error : {}", e.getMessage());
                }
            }

        } catch (Exception e) {
            LOGGER.error("confirmResults error : {}", e.getMessage());
            userPhoneList = null;
            // throw new BusinessException("回单异常");
        }
        if (null != userPhoneList) {
            // 发送回单短信
            for (JSONObject j : userPhoneList) {
                sendMessageService.sendResultDriverMessage(j.getString("orderCode"), j.getString("phone"));
            }
        }
    }

    @Override
    public String getIdsFromRedis() throws Exception {
        LOGGER.info("getIdsFromRedis excute ... ");

        //查询派单队列中的所以运单信息
        List<TmsQueueOrderVo> orderVos = TmsQueueApi.orderList();
        if (CollectionUtils.isNotEmpty(orderVos)) {

            //运单主键
            List<String> stringIds = orderVos.stream().map(TmsQueueOrderVo::getWaybillId).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(stringIds)) {

                List<DWaybill> bills = dWaybillService.selectListByIds(stringIds.stream().map(s -> Long.parseLong(s)).collect(Collectors.toList()));

                if (CollectionUtils.isNotEmpty(bills)) {

                    //过滤出未分派的运单
                    bills = bills.stream().filter(b -> b.getUserId() == 0 && b.getWaybillStatus() == DWaybillStatusEnum.SAVE.getValue()).collect(Collectors.toList());

                    if (CollectionUtils.isNotEmpty(bills)) {
                        return String.join(",", bills.stream().map(b -> b.getOrderLineId().toString()).collect(Collectors.toList()));
                    }
                }
            }
        }
        return null;
    }

    @Override
    public String selectRecalculateOrderIds() throws Exception {
        LOGGER.info("OrderServiceImpl.selectRecalculateOrderIds start ...");
        List<DWaybill> list = dWaybillService.selectListByStatus(Arrays.asList(DWaybillStatusEnum.SAVE.getValue()));
        if (CollectionUtils.isNotEmpty(list)) {
            return String.join(",", list.stream().map(d -> d.getOrderLineId().toString()).collect(Collectors.toList()));
        }
        return null;
    }

    @Override
    public String getListByStatus(List<Integer> status) {
        StringBuffer sql = new StringBuffer("SELECT order_line_id FROM d_waybill WHERE user_id > 0");
        String where = "";
        sql.append(" AND waybill_status IN ( ");
        int size = status.size();
        for (int i = 0; i < size; i++) {
            int iVal = status.get(i);
            if (i + 1 == size) {
                where += iVal;
            } else {
                where += iVal + ", ";
            }
        }
        sql.append(where).append(")");
        List<Map<String, Object>> list = JdbcTemplateUtils.getJdbcTemplate().queryForList(sql.toString());
        if (null != list && list.size() > 0) {
            StringBuffer sb = new StringBuffer();
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                Map<String, Object> m = list.get(i);
                if (i + 1 == listSize) {
                    sb.append(m.get("order_line_id"));
                } else {
                    sb.append(m.get("order_line_id")).append(",");
                }
            }
            return sb.toString();
        }
        return null;
    }

    @Override
    public void recalculateOrderCostByWaybillIds(String waybillIds) throws Exception {
        LOGGER.info("OrderServiceImpl.recalculateOrderCost params : {}", waybillIds);

        if (StringUtils.isBlank(waybillIds)) {
            LOGGER.error("OrderServiceImpl.recalculateOrderCostByWaybillIds params waybillIds must not be null");
            throw new IllegalArgumentException("主键不能为空");
        }

        String[] ids = waybillIds.split(",");
        if ( ids.length > 0 ) {
            for (int i = 0; i < ids.length; i++) {
                DWaybill waybill = dWaybillService.getByPrimaryId(Long.parseLong(ids[i]));
                if (null != waybill) {
                    dWaybillService.addDWaybillCost(DWaybillFeeDetailCostTypeEnum.RECLAC_COST, waybill);
                }
            }
        } else {
            LOGGER.error("OrderServiceImpl.recalculateOrderCostByWaybillIds params waybillIds size < 1");
            throw new IllegalArgumentException("主键不能为空");
        }

    }


    @Override
    public void getReturnQueue(List<TmsOrder> tmsOrders) {
        tmsOrders.forEach(tmsOrder -> {
            String orderCode = tmsOrder.getVcorderno();
            DWaybill dWaybill = null;
            try {
                dWaybill = dWaybillService.getByTmsOrderCode(orderCode);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Long waybillId = dWaybill.getId();
            Long orderLineId = dWaybill.getOrderLineId();

            //查询队列中是否有该订单,不过不存在判断该订单的数据是否符合入队要求
            TmsQueueOrderVo tqv = TmsQueueApi.getOrder(waybillId.toString(), orderLineId.toString());
            if (tqv == null) {
                //反序列化费用信息
                OrderCostTo orderCostTo;
                if (StringUtils.isNotBlank(tmsOrder.getOrdercost())) {
                    orderCostTo = JSONObject.parseObject(tmsOrder.getOrdercost().replaceAll("\"", ""), OrderCostTo.class);
                    LOGGER.info("waybillId:{}, orderCost : {}", waybillId, orderCostTo);
                    if (orderCostTo != null) {
                        if (orderCostTo.getKm().compareTo(BigDecimal.ZERO) == 1 &&
                                orderCostTo.getPrice().compareTo(BigDecimal.ZERO) == 1 &&
                                orderCostTo.getKilometer().compareTo(BigDecimal.ZERO) == 1 &&
                                orderCostTo.getFuelstandard().compareTo(BigDecimal.ZERO) == 1 &&
                                orderCostTo.getMarketprice().compareTo(BigDecimal.ZERO) == 1) {

                            //加入队列
                            TmsQueueOrderVo vo = new TmsQueueOrderVo();
                            vo.setWaybillId(waybillId.toString());
                            vo.setTmsSerialNo(orderLineId.toString());
                            vo.setFrom(tmsOrder.getVcstartcity());
                            vo.setTo(tmsOrder.getVccityname());
                            vo.setUrgent(tmsOrder.getIurgent() == 1 ? true : false);
                            try {
                                tmsQueueService.appendOrder(vo);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                        }

                    }
                }
            }
        });

    }

    @Override
    public void addQueue(TmsOrder tmsOrder, DWaybill waybill) throws Exception {
        LOGGER.info("OrderServiceImpl.addQueue params : {}, {}", tmsOrder, waybill);

        if (null == tmsOrder) {
            LOGGER.error("OrderServiceImpl.addQueue param tmsOrder must not be null");
            throw new IllegalArgumentException("TMS订单不能为空");
        }

        if (null == waybill) {
            LOGGER.error("OrderServiceImpl.addQueue param waybill must not be null");
            throw new IllegalArgumentException("运单不能为空");
        }


        /**
         * 加入队列
         */
        TmsQueueOrderVo vo = new TmsQueueOrderVo();
        vo.setWaybillId(waybill.getId().toString());
        vo.setTmsSerialNo(waybill.getOrderLineId().toString());
        vo.setFrom(tmsOrder.getVcstartcity());
        vo.setTo(tmsOrder.getVccityname());
        vo.setUrgent(tmsOrder.getIurgent() == 1 ? true : false);
        tmsQueueService.appendOrder(vo);
    }

    @Override
    public String getOrderLineIdsByStatus(List<Integer> status) {
        StringBuffer sql = new StringBuffer("SELECT order_line_id FROM d_waybill WHERE user_id > 0");
        String where = "";
        sql.append(" AND recovery_time IS NULL ");
        sql.append(" AND waybill_status IN ( ");
        int size = status.size();
        for (int i = 0; i < size; i++) {
            int iVal = status.get(i);
            if (i + 1 == size) {
                where += iVal;
            } else {
                where += iVal + ", ";
            }
        }
        sql.append(where).append(")");
        List<Map<String, Object>> list = JdbcTemplateUtils.getJdbcTemplate().queryForList(sql.toString());
        if (CollectionUtils.isNotEmpty(list)) {
            StringBuffer sb = new StringBuffer();
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                Map<String, Object> m = list.get(i);
                if (i + 1 == listSize) {
                    sb.append(m.get("order_line_id"));
                } else {
                    sb.append(m.get("order_line_id")).append(",");
                }
            }
            return sb.toString();
        }
        return null;
    }


    @Override
    public List<Integer> getOrderLineIdListByStatus(List<Integer> status) {
        List<Integer> lineidList= Lists.newArrayList();

        StringBuffer sql = new StringBuffer("SELECT order_line_id FROM d_waybill WHERE user_id > 0");
        String where = "";
        sql.append(" AND recovery_time IS NULL ");
        sql.append(" AND waybill_status IN ( ");
        int size = status.size();
        for (int i = 0; i < size; i++) {
            int iVal = status.get(i);
            if (i + 1 == size) {
                where += iVal;
            } else {
                where += iVal + ", ";
            }
        }

        sql.append(where).append(")");
        List<Map<String, Object>> list = JdbcTemplateUtils.getJdbcTemplate().queryForList(sql.toString());
        if (CollectionUtils.isNotEmpty(list)) {
            StringBuffer sb = new StringBuffer();
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                Map<String, Object> m = list.get(i);
                lineidList.add(Integer.parseInt(m.get("order_line_id").toString()));
            }
            return lineidList;
        }

        return lineidList;
    }

}
